/* 
	Game.h

	+ = blank
	@ = black -- client
	O = white -- server

	game_state
		0 = continue state
		1 = winning state
		2 = tied state
*/

#include "Move.h"

#include <string>
#include <vector>
#include <iostream>
#include <sstream>
#include <stack>
#include <algorithm>

#include <stdlib.h>	

#define BLANK '+'
#define BLACK '@'
#define WHITE 'O'
#define MISC  'X'

using namespace std;

struct Board
{
	char two_d[15][15];

	Board()
	{
		for(size_t i = 0; i < 15; i++)
			for(size_t j = 0; j < 15; j++)
				two_d[i][j] = BLANK;
	}

	bool validate_move(int row, int col)
	{

		//Commented out the print statements
		//We need to validate moves for possible_moves()

		if( row < 1 || row > 15)
		{
			//cerr << "Error: invalid row" << endl;
			return false;
		}
		if( col < 1 || col > 15)
		{
			//cerr << "Error: invalid column" << endl;
			return false;
		}
		if(two_d[row-1][col-1] == BLANK)
			return true;
		else
			//cerr << "Error: space taken " << i<<" "<< j<<endl;

		return false;
	}
};


class Game
{
	
	

	public:
    vector<Move> moves;
	Board board;

	Game()
	{
        vector<Move> moves();
		/*
		for(int i = 0; i < 15; ++i)
			for(int j = 0; j < 15; ++j)
				board[i][j] = BLANK;
				*/
	}

	Game& operator=(const Game& game);


	const char get_pos(const int i, const int j);
	const string last_move();

	// check if the move is within the board and if occupied
	bool validate_move(const int i, const int j);
	// move param = ints 1-15
	void move(const int i, const int j, const char p);
	void move(Move m);
	// push move onto stack for undo
	void log_move(const Move m);
	void undo();
    void undo1();

	bool check_pos(int r, int c, int sx, int sy);

	int check_state();
	int check_tie();

	int moves_left();
	
	// static bool check_vert(Game b, Move m);
	// static bool check_horizon(Game b, Move m);
	// static bool check_diagnol(Game b, Move m);
	// static bool check_forward(Game b, Move m);
	// static bool check_back(Game b, Move m);

	// print to stdout
	string display();
	void display_server();
	vector<Move> possible_moves();
};


struct Node
{
	Game* game;
	int value;
	bool max;

    Node(): game(), value(0), max(false){}
    
	Node(Game* g, bool l): game(g), value(0), max(l) {}
    
    Node& operator=(const Node& n)
    {
        game = n.game;
        value = n.value;
        max = n.max;
        
        return *this;
    }
};

template<typename T>
void removeDuplicates(std::vector<T>& vec)
{
    std::sort(vec.begin(), vec.end());
    vec.erase(std::unique(vec.begin(), vec.end()), vec.end());
}
